﻿/*  ------------------------------------------------------------------------
	 NQ Common Services Library
	 
	 Homepage: http://www.awzhome.de/
	 ------------------------------------------------------------------------
	 
	 The contents of this file are subject to the Mozilla Public License
	 Version 1.1 (the "License"); you may not use this file except in
	 compliance with the License. You may obtain a copy of the License at
	 http://www.mozilla.org/MPL/
	 
	 Software distributed under the License is distributed on an "AS IS"
	 basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	 License for the specific language governing rights and limitations
	 under the License.
	
	 The Original Code is code of NQ Common Services Library.

	 The Initial Developer of the Original Code is Andreas Weizel.
	 Portions created by the Initial Developer are
	 Copyright (C) 2011-2012 Andreas Weizel. All Rights Reserved.
	 
	 Contributor(s): (none)
	 
	 Alternatively, the contents of this file may be used under the terms
	 of the GNU General Public License Version 2.0 or later (the "GPL"),
	 or the GNU Lesser General Public License Version 2.1 or later (the
	 "LGPL"), in which case the provisions of the GPL or the LGPL are
	 applicable instead of those above. If you wish to allow use of your
	 version of this file only under the terms of the GPL or the LGPL and
	 not to allow others to use your version of this file under the MPL,
	 indicate your decision by deleting the provisions above and replace
	 them with the notice and other provisions required by the GPL or the
	 LGPL. If you do not delete the provisions above, a recipient may use
	 your version of this file under the terms of any of the MPL, the GPL
	 or the LGPL.
	 ------------------------------------------------------------------------
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AWZhome.NQ.Core;
using System.Windows.Controls;
using AWZhome.NQ.Core.Fluent;
using AWZhome.NQ.CommonServices;
using AWZhome.NQ.CommonServices.Visual;
using System.Windows;
using System.Windows.Forms.Integration;
using AWZhome.awzBoxes;
using System.IO;
using System.Reflection;
using System.Windows.Input;

namespace AWZhome.NQ.CommonServices.Services
{
	[NQExportedService]
	[NQServiceSubstitute(typeof(Services.IViewManagerService))]
	public class AwzBoxesViewManagerService : Services.IAwzBoxesViewManagerService
	{

		private class PersistServiceLayoutProvider : ILayoutStorageProvider
		{
			private AwzBoxesViewManagerService _viewManager;
			private Dictionary<string, string> _boxItemConfigurations;
			private Dictionary<string, string> _generalConfigurations;
			private List<string> _lastOpenBoxItems;

			public PersistServiceLayoutProvider(AwzBoxesViewManagerService viewManager)
			{
				_viewManager = viewManager;
				_boxItemConfigurations = new Dictionary<string, string>();
				_generalConfigurations = new Dictionary<string, string>();
				_lastOpenBoxItems = new List<string>();
			}

			public void LoadConfigurations()
			{
				_boxItemConfigurations.Clear();
				_generalConfigurations.Clear();
				_lastOpenBoxItems.Clear();

				// Get the layout settings for the BoxItems from persistence
				IConfigManager configService = ServiceCore
					.Get<Services.IConfigService>()
					.Instance;

				var boxItemConfigs = configService.GetContainerListSetting(
					_viewManager._parentContainer.Name, "boxItemLayout");
				if (boxItemConfigs != null)
				{
					foreach (var item in boxItemConfigs)
					{
						if ((item != null) && !item.IsEmpty)
						{
							string[] parts = item.AsString().Split(new char[] { '|' }, 2);
							if ((parts != null) && (parts.Length > 1))
							{
								_boxItemConfigurations[parts[0]] = parts[1];
							}
						}
					}
				}

				// General settings of awzBoxes
				var generalConfigs =
					configService.GetContainerListSetting(_viewManager._parentContainer.Name, "boxGeneralLayout");
				if (generalConfigs != null)
				{
					foreach (ConfigData configValue in generalConfigs)
					{
						string[] keyValuePair = configValue.AsString("").Split(new char[] { '|' }, 2);
						if ((keyValuePair != null) && (keyValuePair.Length == 2))
						{
							_generalConfigurations.Add(keyValuePair[0], keyValuePair[1]);
						}
					}
				}

				// List of last open BoxItems
				var lastOpenItemConfigs = configService.GetContainerListSetting(
					_viewManager._parentContainer.Name, "lastOpenBoxItems");
				if (lastOpenItemConfigs != null)
				{
					foreach (var item in lastOpenItemConfigs)
					{
						if ((item != null) && !item.IsEmpty)
						{
							_lastOpenBoxItems.Add(item.AsString());
						}
					}
				}
			}

			public void SaveConfigurations()
			{
				// Collect all settings and save them as a list setting through PersistService
				IPersistManager persistService = ServiceCore
					.Get<Services.IPersistService>()
					.Instance;

				// Save layout settings
				List<ConfigData> layoutSettings = new List<ConfigData>();
				foreach (var itemLayout in _boxItemConfigurations)
				{
					layoutSettings.Add(new ConfigData().FromString(itemLayout.Key + "|" + itemLayout.Value));
				}
				persistService.SetContainerListSetting(
					_viewManager._parentContainer.Name, "boxItemLayout", layoutSettings);

				List<ConfigData> generalLayoutSettings = new List<ConfigData>();
				foreach (var itemLayout in _generalConfigurations)
				{
					generalLayoutSettings.Add(new ConfigData().FromString(itemLayout.Key + "|" + itemLayout.Value));
				}
				persistService.SetContainerListSetting(
					_viewManager._parentContainer.Name, "boxGeneralLayout", generalLayoutSettings);

				// Save last open BoxItems
				List<ConfigData> lastOpenItemsSetting = new List<ConfigData>();
				foreach (string lastOpenBox in _lastOpenBoxItems)
				{
					lastOpenItemsSetting.Add(new ConfigData().FromString(lastOpenBox));
				}
				persistService.SetContainerListSetting(
					_viewManager._parentContainer.Name, "lastOpenBoxItems", lastOpenItemsSetting);
			}

			#region ILayoutStorageProvider Member

			public string GetBoxItemConfiguration(string boxItemName)
			{
				if (_boxItemConfigurations.ContainsKey(boxItemName))
				{
					return _boxItemConfigurations[boxItemName];
				}
				else
				{
					return null;
				}
			}

			public void SetBoxItemConfiguration(string boxItemName, string configuration)
			{
				_boxItemConfigurations[boxItemName] = configuration;
			}

			public string[] GetLastOpenBoxItems()
			{
				return _lastOpenBoxItems.ToArray();
			}

			public void SaveLastOpenBoxItems(string[] openBoxItems)
			{
				_lastOpenBoxItems.Clear();
				_lastOpenBoxItems.AddRange(openBoxItems);
			}

			public BoxItem RestoreBoxItem(string name)
			{
				BoxItem existingBoxItem = _viewManager.GetBoxItemFromName(name);
				if (existingBoxItem != null)
				{
					return existingBoxItem;
				}
				else
				{
					string[] viewSplit = name.Split('ÿ');
					if ((viewSplit != null) && (viewSplit.Length >= 3))
					{
						// Get the session instance
						ISessionManager sessionManager = ServiceCore
							.Get<Services.ISessionManagerService>()
							.Instance;
						ISession session = sessionManager[viewSplit[1].Replace('þ', '|')];
						if (session != null)
						{
							// Create the new view instance and set its context
							Type serviceIfcType = Type.GetType(viewSplit[0], false);
							if (serviceIfcType != null)
							{
								try
								{
									IView newView = ServiceCore
										.Create<IView>()
										.UsingType(serviceIfcType)
										.DependentOn<ISession>(session)
										.Instance;
									newView.Initialize(viewSplit[2]);

									// Add the view to view manager
									_viewManager.AddView(newView, true, true);
									// Now return the BoxItem of the new view
									existingBoxItem = _viewManager._boxItems[newView.Name];
									existingBoxItem.Name = name;
									return existingBoxItem;
								}
								catch (Exception)
								{
									// If an error occurs on view initialization, don't restore it
									return null;
								}
							}
						}
					}
				}

				return null;
			}

			public void SetGeneralConfiguration(string key, string value)
			{
				_generalConfigurations[key] = value;
			}

			public string GetGeneralConfiguration(string key)
			{
				if (_generalConfigurations.ContainsKey(key))
				{
					return _generalConfigurations[key];
				}
				else
				{
					return null;
				}
			}

			#endregion
		}

		private IContainer _parentContainer = null;
		private IResourceManager _servRes = null;
		private IBarManager _servBar = null;
		private IPersistManager _servPersist = null;

		private Dictionary<string, IView> _views = new Dictionary<string, IView>();
		private Dictionary<string, BoxItem> _boxItems = new Dictionary<string, BoxItem>();
		private IView _activeView = null;
		private IView _contextView = null;
		private AwzBoxesViewManagerDock _viewManDock;
		private PersistServiceLayoutProvider _layoutStorageProvider;

		public AwzBoxesViewManagerService(IContainer parent)
		{
			_parentContainer = parent;
			Panel parentControl = _parentContainer.ClientAreaObject as Panel;

			_servRes = ServiceCore
				.Get<Services.IResourceService>()
				.Instance;
			_servBar = _parentContainer.BarService;
			_servPersist = ServiceCore
				.Get<Services.IPersistService>()
				.Instance;

			_servBar.ItemClicked += new EventHandler<BarItemClickedEventArgs>(_servBar_ItemClicked);

			if (parentControl != null)
			{
				// Create storage provider for awzBoxes
				_layoutStorageProvider = new PersistServiceLayoutProvider(this);

				// Create ViewManagerDock control
				_viewManDock = new AwzBoxesViewManagerDock();
				_viewManDock.BoxWindowContainer.LayoutStorageProvider = _layoutStorageProvider;
				_viewManDock.DataContext = this;
				_viewManDock.Loaded += new RoutedEventHandler(_viewManDock_Loaded);
				((BoxArea) _viewManDock.BoxWindowContainer.InnerAreaControl).ActiveBoxItemChanged += new EventHandler<ActiveBoxItemChangedEventArgs>(AwzBoxesViewManagerService_ActiveBoxItemChanged);
				parentControl.Children.Add(_viewManDock);
				_viewManDock.Visibility = Visibility.Visible;
			}

			// Create menus
			this.CreateMenus();
		}

		#region INQViewManagerService Member

		public event EventHandler<ActiveViewChangedEventArgs> ActiveViewChanged;

		public void AddView(IView newView)
		{
			this.AddView(newView, true);
		}

		public void AddView(IView newView, bool activate)
		{
			this.AddView(newView, activate, false);
		}

		public void RemoveView(string viewName)
		{
			if (_views.ContainsKey(viewName))
			{
				IView delview = _views[viewName];

				// Check if the view can be closed
				if (delview.CanBeClosed)
				{
					if (delview.RequestClosing())
					{
						if (_boxItems.ContainsKey(viewName))
						{
							BoxItem closedBoxItem = _boxItems[viewName];
							_boxItems.Remove(viewName);
							closedBoxItem.Closed -= viewBoxItem_Closed;
							closedBoxItem.DirectionChanged -= viewBoxItem_DirectionChanged;
							closedBoxItem.ContextMenuRequested -= viewBoxItem_ContextMenuRequested;
							closedBoxItem.Close();
						}

						// Let the view save its settings
						delview.SaveContents(ViewSaveReason.ExplicitlyClosed);

						// Delete the view object and its panel
						delview.ViewManager = null;
						_views.Remove(viewName);

						if (this.CountByDisplayMode(ViewDisplayMode.InClientArea) == 0)
						{
							// The last view is about to be closed, clear active view reference to be safe
							this.ActiveView = null;
						}

						// Remove item from window menu
						_servBar.GetItem("mnuWindow").RemoveItem("mnuWindow.Item." + viewName);
						_servBar.RemoveItem("mnuWindow.Item." + viewName);

						// Hide/show some menu items depending on open view count
						int tabCount = this.CountByDisplayMode(ViewDisplayMode.InClientArea);
						_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = (tabCount > 0);
						_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = (tabCount > 0);
						_servBar.GetItem("mnuWindow.Sep1").ItemVisible = (tabCount > 0);
					}
				}
			}
			else
			{
				// We don't know that view name
				this.RaiseViewNotFoundException(viewName);
			}
		}

		public void UpdateView(IView view, bool internalChange)
		{
			if (_views.ContainsKey(view.Name))
			{
				BoxItem boxItem = _boxItems[view.Name];
				boxItem.Title = view.DisplayName;
				boxItem.Icon = view.Icon;
				boxItem.IsHighlighted = view.IsChanged;
				boxItem.IsChanged = view.IsDirty;
				boxItem.AllowedDockAreas = this.DisplayMode2DockDirection(view.DockingType);
				boxItem.IsClosable = view.CanBeClosed;
				boxItem.ToolTip = view.ToolTip;
				boxItem.IsRestored = view.IsPersisted;

				if (internalChange)
				{
					view.DisplayMode = this.DockDirection2DisplayMode(boxItem.Direction);
				}
				else
				{
					BoxItemDockDirection dockDirection = this.DisplayMode2DockDirection(view.DisplayMode);
					if (dockDirection != boxItem.Direction)
					{
						boxItem.Direction = dockDirection;
					}
				}

				// Update window menu
				string itemname = "mnuWindow.Item." + view.Name;
				if (_servBar.ItemExists(itemname))
				{
					_servBar.GetItem(itemname).ItemVisible = (view.DisplayMode == ViewDisplayMode.InClientArea);
				}
			}

			// Hide/show some menu items depending on open view count
			int tabCount = this.CountByDisplayMode(ViewDisplayMode.InClientArea);
			_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = (tabCount > 0);
			_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = (tabCount > 0);
			_servBar.GetItem("mnuWindow.Sep1").ItemVisible = (tabCount > 0);

			_parentContainer.Update();
		}

		public void MoveView(IView view, IViewManager destManager)
		{
			// Currently not implemented
		}

		public int CountByDisplayMode(ViewDisplayMode displayMode)
		{
			return _views.Values.Count(view => view.DisplayMode == displayMode);
		}

		public void LoadSettings()
		{

		}

		public void SaveSettings()
		{
			// Save the settings of all open views
			foreach (IView view in _views.Values)
			{
				view.SaveContents(ViewSaveReason.ContainerClosed);
			}

			if (_activeView != null)
			{
				_servPersist.SetContainerSetting(
					_parentContainer.Name, "lastOpenView", new ConfigData().FromString(_activeView.Name));
			}

			_viewManDock.BoxWindowContainer.SaveLayout();
			_layoutStorageProvider.SaveConfigurations();
		}

		public IView ActiveView
		{
			get
			{
				return _activeView;
			}
			set
			{
				if (value != _activeView)
				{
					if (value != null)
					{
						if (_views.ContainsValue(value))
						{
							// Activate the view's BoxItem
							_viewManDock.BoxWindowContainer.InnerBoxArea.ActiveBoxItem = _boxItems[value.Name];
						}
						else
						{
							// View not found
							RaiseViewNotFoundException(value.Name);
						}
					}
					else
					{
						// The new view is "null"
						_activeView = null;
						this.OnActiveViewChanged(_activeView, null);
					}
				}
			}
		}

		public ISession ActiveSession
		{
			get
			{
				if (_activeView != null)
				{
					return _activeView.Session;
				}
				else
				{
					// Get default session
					ISessionManager sessionManager = ServiceCore
						.Get<Services.ISessionManagerService>()
						.Instance;
					return sessionManager.DefaultSession;
				}
			}
		}

		public IContainer Container
		{
			get
			{
				return _parentContainer;
			}
		}

		#endregion

		#region INQCollectionService<string,INQViewService> Member

		public IView this[string key]
		{
			get
			{
				if (_views.ContainsKey(key))
				{
					return _views[key];
				}
				else
				{
					return null;
				}
			}
		}

		public int Count
		{
			get
			{
				return _views.Count;
			}
		}

		#endregion

		#region IEnumerable<INQViewService> Member

		public IEnumerator<IView> GetEnumerator()
		{
			return ((IEnumerable<IView>) _views.Values).GetEnumerator();
		}

		#endregion

		#region IEnumerable Member

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return ((System.Collections.IEnumerable) _views.Values).GetEnumerator();
		}

		#endregion

		#region Other private methods

		private void _servBar_ItemClicked(object sender, BarItemClickedEventArgs e)
		{
			switch (e.Item.ItemKey)
			{
				case "mnuWindow.CloseCurrent":
					if (_activeView != null)
					{
						// Close current view
						this.RemoveView(_activeView.Name);
					}
					break;

				case "mnuWindow.CloseAll":
					// Close all views
					string[] viewkeys = new string[_views.Count];
					_views.Keys.CopyTo(viewkeys, 0);
					for (int i = 0; i < viewkeys.Length; i++)
					{
						this.RemoveView(_views[viewkeys[i]].Name);
					}
					break;

				case "cmnuViewManagerTab.CloseCurrent":
					if (_contextView != null)
					{
						// Close current tab
						RemoveView(_contextView.Name);
						_contextView = null;
					}
					break;

				case "cmnuViewManagerTab.CloseOther":
					// Close all tabs besides the one which is selected
					if (_contextView != null)
					{
						List<IView> delviews = new List<IView>();
						foreach (IView viewItem in _views.Values)
						{
							if ((viewItem != _contextView) && (viewItem.DisplayMode == _contextView.DisplayMode))
							{
								delviews.Add(viewItem);
							}
						}
						for (int i = 0; i < delviews.Count; i++)
						{
							RemoveView(delviews[i].Name);
						}
						_contextView = null;
					}
					break;

				default:
					if (e.Item.ItemKey.StartsWith("mnuWindow.Item."))
					{
						// Activate the view
						this.ActiveView = _views[e.Item.ItemKey.Substring("mnuWindow.Item.".Length)];
					}
					break;
			}
		}

		private void _viewManDock_Loaded(object sender, RoutedEventArgs e)
		{
			_layoutStorageProvider.LoadConfigurations();
			_viewManDock.BoxWindowContainer.RestoreLayout();

			// Load last open view
			ConfigData lastOpenViewConf =
				_servPersist.GetContainerSetting(_parentContainer.Name, "lastOpenView");
			if (lastOpenViewConf != null)
			{
				if (_views.ContainsKey(lastOpenViewConf.AsString()))
				{
					this.ActiveView = _views[lastOpenViewConf.AsString()];
				}
			}
		}

		private void AwzBoxesViewManagerService_ActiveBoxItemChanged(object sender, ActiveBoxItemChangedEventArgs e)
		{
			// Get tab from view
			IView selview = null;
			IView oldview = _activeView;

			// Get the view, the active document belongs to
			string viewKey = this.GetViewNameFromBoxItem(e.NewBoxItem);
			if ((e.NewBoxItem != null) && _views.ContainsKey(viewKey))
			{
				selview = _views[viewKey];
			}

			if (selview != null)
			{
				if (oldview != null)
				{
					// Hide the view
					oldview.Deactivate(selview);
					string itemname = "mnuWindow.Item." + oldview.Name;
					if (_servBar.ItemExists(itemname))
					{
						_servBar.GetItem(itemname).ItemChecked = false;
					}
				}
				// Select the view
				_activeView = selview;
				if (_activeView != null)
				{
					_activeView.Activate(oldview);
					// Make the new view visible
					string itemname = "mnuWindow.Item." + _activeView.Name;
					if (_servBar.ItemExists(itemname))
					{
						_servBar.GetItem(itemname).ItemChecked = true;
					}
				}
			}

			this.OnActiveViewChanged(oldview, selview);
		}

		private void viewBoxItem_DirectionChanged(object sender, DirectionChangedEventArgs e)
		{
			BoxItem boxItem = sender as BoxItem;
			if (boxItem != null)
			{
				string viewName = this.GetViewNameFromBoxItem(boxItem);
				if ((viewName != null) && (_views.ContainsKey(viewName)))
				{
					this.UpdateView(_views[viewName], true);
				}
			}
		}

		private void viewBoxItem_Closed(object sender, EventArgs e)
		{
			// Remove the view
			BoxItem boxItem = sender as BoxItem;
			if (boxItem != null)
			{
				string viewName = this.GetViewNameFromBoxItem(boxItem);
				if (viewName != null)
				{
					this.RemoveView(viewName);
				}
			}
		}

		private void viewBoxItem_ContextMenuRequested(object sender, ContextMenuRequestedEventArgs e)
		{
			string viewName = this.GetViewNameFromBoxItem((BoxItem) sender);
			if (!String.IsNullOrEmpty(viewName) && _views.ContainsKey(viewName))
			{
				_contextView = _views[viewName];
				_servBar.GetItem("cmnuViewManagerTab.CloseCurrent").ItemEnabled = _contextView.CanBeClosed;
				Point point = Mouse.GetPosition(_viewManDock);
				Point screenPoint = (_viewManDock.PointToScreen(point));
				_servBar.GetBand("cmnuViewManagerTab").ShowAsContextMenu((int) screenPoint.X, (int) screenPoint.Y);
			}
		}

		private void AddView(IView newView, bool activate, bool restore)
		{
			IView oldview = _activeView;

			// Exit if this view is already here
			if (_views.ContainsKey(newView.Name))
			{
				return;
			}

			// Remove the view from any other view manager
			if (newView.ViewManager != null)
			{
				newView.ViewManager.RemoveView(newView.Name);
			}

			// Add the view object to internal list
			_views.Add(newView.Name, newView);
			newView.ViewManager = this;

			// Display general items of "Window" menu
			if (_views.Count > 0)
			{
				_servBar.GetItem("mnuWindow.CloseCurrent").ItemEnabled = true;
				_servBar.GetItem("mnuWindow.CloseAll").ItemEnabled = true;
				_servBar.GetItem("mnuWindow.Sep1").ItemVisible = true;
			}

			// Create item in window menu (must be done before creating the BoxItem)
			string windowItemKey = "mnuWindow.Item." + newView.Name;
			try
			{
				IBarItem viewMenuItem = _servBar.CreateItem(windowItemKey, BarItemType.MenuItem);
				viewMenuItem.ItemText = newView.DisplayName;
				_servBar.GetItem("mnuWindow").InsertItem(windowItemKey, "mnuWindow.Sep1", false);
			}
			catch (BarDefinitionException ex)
			{
				ServiceCore.Log.From(this).Error(ex);
			}

			// Create new BoxItem for the view
			BoxItem viewBoxItem = new BoxItem();
			if (!restore)
			{
				viewBoxItem.Name = this.GenerateBoxItemName(newView);
			}
			_boxItems.Add(newView.Name, viewBoxItem);
			viewBoxItem.Closed += new EventHandler(viewBoxItem_Closed);
			viewBoxItem.DirectionChanged += new EventHandler<DirectionChangedEventArgs>(viewBoxItem_DirectionChanged);
			viewBoxItem.ContextMenuRequested += new EventHandler<ContextMenuRequestedEventArgs>(viewBoxItem_ContextMenuRequested);

			// If the view's control is a WinForms control, create a WindowsFormsHost around it
			if (newView.DisplayedObject is System.Windows.Forms.Control)
			{
				WindowsFormsHost winFormsHost = new WindowsFormsHost();
				winFormsHost.Child = (System.Windows.Forms.Control) newView.DisplayedObject;
				((System.Windows.Forms.Control) newView.DisplayedObject).Visible = true;
				winFormsHost.Visibility = Visibility.Visible;
				viewBoxItem.Content = winFormsHost;
			}
			else if (newView.DisplayedObject is System.Windows.Controls.Control)
			{
				// The displayed control is a WPF control
				viewBoxItem.Content = (System.Windows.Controls.Control) newView.DisplayedObject;
			}

			// Eventually update the BoxItem (AddBoxItem() automatically restores layout settings, if possible)
			this.UpdateView(newView, false);
			if (!restore)
			{
				_viewManDock.BoxWindowContainer.AddBoxItem(viewBoxItem);
			}

			// Let the view load its settings
			newView.LoadContents();

			if (!restore)
			{
				if (newView.DisplayMode == ViewDisplayMode.InClientArea)
				{
					if (activate)
					{
						// Set the new view active
						this.ActiveView = newView;
					}
				}
				else if (newView.DisplayMode == ViewDisplayMode.Floating)
				{
					// Floating windows can also be activated
					if (activate)
					{
						_viewManDock.BoxWindowContainer.InnerBoxArea.ActiveBoxItem = viewBoxItem;
					}
				}
			}
		}

		private void RaiseViewNotFoundException(string viewName)
		{
			throw new Exception("View " + viewName + " not found.");
		}

		private void OnActiveViewChanged(IView oldview, IView newview)
		{
			// Set visibility of dependent bar items in the container
			if (_parentContainer.BarService != null)
			{
				if (oldview != null)
				{
					SetBarItemVisibility(oldview, newview, false);
				}
				if (newview != null)
				{
					SetBarItemVisibility(newview, oldview, true);
				}
			}

			// Set the window menu item of the current view to top
			if (newview != null)
			{
				string windowItemKey = "mnuWindow.Item." + newview.Name;
				_servBar.GetItem("mnuWindow").RemoveItem(windowItemKey);
				_servBar.GetItem("mnuWindow").InsertItem(windowItemKey, "mnuWindow.Sep1", false);
			}

			_parentContainer.Update();

			if ((this.ActiveViewChanged != null) && (oldview != newview))
			{
				this.ActiveViewChanged(this, new ActiveViewChangedEventArgs(oldview, newview));
			}
		}

		private void SetBarItemVisibility(IView view, IView oldview, bool active)
		{
			bool suppressView = false;
			bool suppressSess = false;

			Type viewService = NQServiceManager.Instance.GetServiceInfoFromObject(view).ServiceInterface;
			Type viewSubstService = NQServiceManager.Instance.GetSubstitutingService(viewService);

			// Abort if the view or session service name is the same as the one of the old view
			if (oldview != null)
			{
				// Has the active view service name changed?
				Type viewServiceOld = NQServiceManager.Instance.GetServiceInfoFromObject(oldview).ServiceInterface;
				Type viewSubstServiceOld = NQServiceManager.Instance.GetSubstitutingService(viewServiceOld);
				suppressView = ((viewService == viewServiceOld) || ((viewSubstService != null) && (viewSubstService == viewSubstServiceOld)));
			}

			// Process bar bands and items dependent on a view
			if (!suppressView)
			{
				ProcessBarBands(viewService.FullName, BarItemConditionObject.View, active);
				ProcessBarItems(viewService.FullName, BarItemConditionObject.View, active);
				if (viewSubstService != null)
				{
					ProcessBarBands(viewSubstService.FullName, BarItemConditionObject.View, active);
					ProcessBarItems(viewSubstService.FullName, BarItemConditionObject.View, active);
				}
			}

			// Process bar bands and items dependent on a session
			if ((view != null) && (view.Session != null))
			{
				Type sessService = NQServiceManager.Instance.GetServiceInfoFromObject(view.Session).ServiceInterface;
				Type sessSubstService = NQServiceManager.Instance.GetSubstitutingService(sessService);

				if (oldview != null)
				{
					// Has the active session service name been changed?
					Type sessServiceOld = NQServiceManager.Instance.GetServiceInfoFromObject(oldview.Session).ServiceInterface;
					Type sessSubstOld = NQServiceManager.Instance.GetSubstitutingService(sessServiceOld);
					suppressSess = ((sessService == sessServiceOld) || ((sessSubstService != null) && (sessSubstService == sessSubstOld)));
				}

				if (!suppressSess)
				{
					ProcessBarBands(sessService.FullName, BarItemConditionObject.Session, active);
					ProcessBarItems(sessService.FullName, BarItemConditionObject.Session, active);
					if (viewSubstService != null)
					{
						ProcessBarBands(sessSubstService.FullName, BarItemConditionObject.Session, active);
						ProcessBarItems(sessSubstService.FullName, BarItemConditionObject.Session, active);
					}
				}
			}
		}

		private void ProcessBarBands(string serviceName, BarItemConditionObject condObject, bool active)
		{
			IBarItemDependency[] depItems;

			// Show/hide bar bands dependent on the active view
			depItems = _parentContainer.BarService.GetBandDependencies(condObject, serviceName);
			if (depItems != null)
			{
				foreach (IBarItemDependency itemdep in depItems)
				{
					IBarBand band = _parentContainer.BarService.GetBand(itemdep.Key);
					if (band != null)
					{
						band.HideAlways = !active;
					}
				}
			}
		}

		private void ProcessBarItems(string serviceName, BarItemConditionObject condObject, bool active)
		{
			IBarItemDependency[] depItems;

			// Show/hide bar items dependent on the active view
			depItems = _parentContainer.BarService.GetItemDependencies(condObject, serviceName);
			if (depItems != null)
			{
				foreach (IBarItemDependency itemdep in depItems)
				{
					IBarItem item = _parentContainer.BarService.GetItem(itemdep.Key);
					if (item != null)
					{
						if (itemdep.IsVisible)
						{
							item.ItemEnabled = active;
						}
						else
						{
							item.HideAlways = !active;
						}
					}
				}
			}
		}

		private BoxItemDockDirection DisplayMode2DockDirection(ViewDisplayMode displayMode)
		{
			BoxItemDockDirection dockDirection = BoxItemDockDirection.NotDocking;

			if ((displayMode & ViewDisplayMode.InClientArea) == ViewDisplayMode.InClientArea)
			{
				dockDirection = dockDirection | BoxItemDockDirection.DockInnerArea;
			}
			if ((displayMode & ViewDisplayMode.DockedTop) == ViewDisplayMode.DockedTop)
			{
				dockDirection = dockDirection | BoxItemDockDirection.DockTop;
			}
			if ((displayMode & ViewDisplayMode.DockedBottom) == ViewDisplayMode.DockedBottom)
			{
				dockDirection = dockDirection | BoxItemDockDirection.DockBottom;
			}
			if ((displayMode & ViewDisplayMode.DockedLeft) == ViewDisplayMode.DockedLeft)
			{
				dockDirection = dockDirection | BoxItemDockDirection.DockLeft;
			}
			if ((displayMode & ViewDisplayMode.DockedRight) == ViewDisplayMode.DockedRight)
			{
				dockDirection = dockDirection | BoxItemDockDirection.DockRight;
			}
			if ((displayMode & ViewDisplayMode.Floating) == ViewDisplayMode.Floating)
			{
				dockDirection = dockDirection | BoxItemDockDirection.Floating;
			}

			return dockDirection;
		}

		private ViewDisplayMode DockDirection2DisplayMode(BoxItemDockDirection dockDirection)
		{
			ViewDisplayMode displayMode = 0;

			if ((dockDirection & BoxItemDockDirection.DockInnerArea) == BoxItemDockDirection.DockInnerArea)
			{
				displayMode = displayMode | ViewDisplayMode.InClientArea;
			}
			if ((dockDirection & BoxItemDockDirection.DockTop) == BoxItemDockDirection.DockTop)
			{
				displayMode = displayMode | ViewDisplayMode.DockedTop;
			}
			if ((dockDirection & BoxItemDockDirection.DockBottom) == BoxItemDockDirection.DockBottom)
			{
				displayMode = displayMode | ViewDisplayMode.DockedBottom;
			}
			if ((dockDirection & BoxItemDockDirection.DockLeft) == BoxItemDockDirection.DockLeft)
			{
				displayMode = displayMode | ViewDisplayMode.DockedLeft;
			}
			if ((dockDirection & BoxItemDockDirection.DockRight) == BoxItemDockDirection.DockRight)
			{
				displayMode = displayMode | ViewDisplayMode.DockedRight;
			}
			if ((dockDirection & BoxItemDockDirection.Floating) == BoxItemDockDirection.Floating)
			{
				displayMode = displayMode | ViewDisplayMode.Floating;
			}

			return displayMode;
		}

		private void CreateMenus()
		{
			IBarBand mainMenu = _servBar.GetMenuBand();

			// Add main window menu
			Stream xmlstream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AWZhome.NQ.CommonServices.menudef.ViewManager.xml");
			_parentContainer.BarService.CreateItemsFromXml(xmlstream);
			xmlstream.Close();
		}

		private string GetViewNameFromBoxItem(BoxItem boxItem)
		{
			string viewKey = _boxItems.Keys.SingleOrDefault(key => _boxItems[key] == boxItem);
			return viewKey;
		}

		private BoxItem GetBoxItemFromName(string name)
		{
			return _boxItems.Values.SingleOrDefault(item => item.Name == name);
		}

		/// <summary>
		/// Generates an unique name for a BoxItem from a view instance.
		/// </summary>
		/// <param name="view">View which the BoxItem belongs to.</param>
		/// <returns>Generated BoxItem name.</returns>
		private string GenerateBoxItemName(IView view)
		{
			// Here we concatenate the qualified name of the view service instance,
			// the session name (here we have to mask the pipe symbol, which may occur in the session name)
			// and the view's context.
			Type interfaceType = NQServiceManager.Instance.GetServiceInfoFromObject(view).ServiceInterface;
			string basicName =
				interfaceType.FullName + ", " + interfaceType.Assembly.GetName().Name
				+ "ÿ" + view.Session.SessionName.Replace('|', 'þ') + "ÿ" + view.Context;
			string generatedName = basicName;

			// Now we must assure that the name is unique
			HashSet<string> boxItemNames = new HashSet<string>();
			foreach (BoxItem boxItem in _boxItems.Values)
			{
				boxItemNames.Add(boxItem.Name);
			}
			int counter = 1;
			while (boxItemNames.Contains(generatedName))
			{
				generatedName = basicName + "ÿ" + counter.ToString();
				counter++;
			}

			return generatedName;
		}

		#endregion

	}
}
